

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using CoreCms.Net.Configuration;
using CoreCms.Net.IRepository;
using CoreCms.Net.IRepository.UnitOfWork;
using CoreCms.Net.IServices;
using CoreCms.Net.Model.Entities;
using CoreCms.Net.Model.ViewModels.Basics;
using CoreCms.Net.Model.ViewModels.UI;
using CoreCms.Net.Utility.Extensions;
using CoreCms.Net.Utility.Helper;
using SqlSugar;


namespace CoreCms.Net.Services
{
    /// <summary>
    /// 用户签到明细表 接口实现
    /// </summary>
    public class CoreCmsUserCheckInDetailsServices : BaseServices<CoreCmsUserCheckInDetails>, ICoreCmsUserCheckInDetailsServices
    {
        private readonly ICoreCmsUserCheckInDetailsRepository _dal;
        private readonly IUnitOfWork _unitOfWork;

        private readonly ICoreCmsSettingServices _settingServices;
        private readonly ICoreCmsUserPointLogServices _userPointLogServices;
        private readonly ICoreCmsUserBalanceServices _userBalanceServices;
        private readonly ICoreCmsCumulativeCheckInRulesServices _cumulativeCheckInRulesServices;
        private readonly ICoreCmsContinuousCheckInRulesServices _continuousCheckInRulesServices;
        private readonly ICoreCmsUserServices _userServices;
        private readonly ICoreCmsUserCheckInServices _userCheckInServices;


        public CoreCmsUserCheckInDetailsServices(IUnitOfWork unitOfWork, ICoreCmsUserCheckInDetailsRepository dal, ICoreCmsSettingServices settingServices, ICoreCmsUserPointLogServices userPointLogServices, ICoreCmsUserBalanceServices userBalanceServices, ICoreCmsCumulativeCheckInRulesServices cumulativeCheckInRulesServices, ICoreCmsContinuousCheckInRulesServices continuousCheckInRulesServices, ICoreCmsUserServices userServices, ICoreCmsUserCheckInServices userCheckInServices)
        {
            this._dal = dal;
            _settingServices = settingServices;
            _userPointLogServices = userPointLogServices;
            _userBalanceServices = userBalanceServices;
            _cumulativeCheckInRulesServices = cumulativeCheckInRulesServices;
            _continuousCheckInRulesServices = continuousCheckInRulesServices;
            _userServices = userServices;
            _userCheckInServices = userCheckInServices;
            base.BaseDal = dal;
            _unitOfWork = unitOfWork;
        }


        /// <summary>
        /// 获取缓存的所有数据
        /// </summary>
        /// <returns></returns>
        public async Task<AdminUiCallBack> DoCheckIn(CoreCmsUserCheckInDetails entity)
        {
            var jm = new AdminUiCallBack();
            try
            {
                var dt = DateTime.Now;
                var dtStr = dt.ToString("yyyy-MM-dd");
                var checkDataStr = entity.checkInData.ToString("yyyy-MM-dd");
                if (dtStr != checkDataStr)
                {
                    jm.msg = "签到日期不符,签到提交日期非今日";
                    return jm;
                }

                var id = await _dal.InsertAsync(entity);

                var userCheckIn = await _userCheckInServices.QueryByClauseAsync(p => p.userId == entity.userId);
                if (userCheckIn != null)
                {
                    //累计签到
                    userCheckIn.cumulativeCheckInCount += 1;

                    //判断是否是连续签到
                    //判断是否是连续签到逻辑是：获取用户最后一次的签到记录，检查查询到的签到记录的checkInData是不是昨天的checkInData，是的话就是连续签到，continuousCheckInCount++,不是的话就是断签了，continuousCheckInCount设置成1重新开始就行了。
                    var lastCheck = await _dal.QueryByClauseAsync(p => p.id < id, true);
                    if (lastCheck == null)
                    {
                        userCheckIn.continuousCheckInCount = 1;
                    }
                    else
                    {
                        var yesterdayDataStr = dt.AddDays(-1).ToString("yyyy-MM-dd");
                        var lastCheckDataStr = lastCheck.checkInData.ToString("yyyy-MM-dd");
                        if (yesterdayDataStr == lastCheckDataStr)
                        {
                            //累加
                            userCheckIn.continuousCheckInCount += 1;
                        }
                        else
                        {
                            //重置
                            userCheckIn.continuousCheckInCount = 1;
                        }
                    }
                    await _userCheckInServices.UpdateAsync(userCheckIn);
                }
                else
                {
                    userCheckIn = new CoreCmsUserCheckIn();
                    userCheckIn.userId = entity.userId;
                    userCheckIn.continuousCheckInCount = 1;
                    userCheckIn.cumulativeCheckInCount = 1;
                    await _userCheckInServices.InsertAsync(userCheckIn);
                }

                //初始化获得的积分
                var point = 0;
                //初始化获得的余额
                var money = 0;


                var allConfigs = await _settingServices.GetConfigDictionaries();
                var showStoresSwitch = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.CheckInIsOpen).ObjectToInt(2);   //是否开启签到
                if (showStoresSwitch == 1)
                {

                    //普通签到赠送处理
                    //签到赠送的数量
                    var checkInCommonNum = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.CheckInCommonNum).ObjectToInt(0);
                    if (checkInCommonNum > 0)
                    {
                        //签到赠送的类别
                        var checkInCommonType = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.CheckInCommonType).ObjectToInt(0);
                        switch (checkInCommonType)
                        {
                            case (int)GlobalEnumVars.CheckInCommonType.积分:
                                point += checkInCommonNum;
                                //储值积分
                                await _userPointLogServices.SetPoint(entity.userId, checkInCommonNum, (int)GlobalEnumVars.UserPointSourceTypes.PointTypeSign, "日历签到，获得" + checkInCommonNum + "积分");
                                break;
                            case (int)GlobalEnumVars.CheckInCommonType.余额:
                                money += checkInCommonNum;
                                //储值余额
                                await _userBalanceServices.Change(entity.userId, (int)GlobalEnumVars.UserBalanceSourceTypes.CheckIn, checkInCommonNum, id.ToString());
                                break;
                        }
                    }

                    //判断累计签到次数是否满足
                    var cumulativeCheckInRules = await _cumulativeCheckInRulesServices.QueryAsync(true, true);
                    //获取用户总签到次数（使用userCheckIn的签到次数统计也可以，但是查询实时数据最可靠。根据个人来）
                    //var cumulativeCheckInCount = await _dal.GetCountAsync(p => p.userId == entity.userId);
                    var cumulativeCheckInCount = userCheckIn.cumulativeCheckInCount;
                    //遍历规则
                    async void Action(CoreCmsCumulativeCheckInRules p)
                    {
                        if (cumulativeCheckInCount == p.days)
                        {
                            switch (p.type)
                            {
                                case (int)GlobalEnumVars.CheckInCommonType.积分:
                                    point += p.num;
                                    //储值积分
                                    await _userPointLogServices.SetPoint(entity.userId, p.num, (int)GlobalEnumVars.UserPointSourceTypes.PointTypeSign, "日历签到，获得" + p.num + "积分");
                                    break;
                                case (int)GlobalEnumVars.CheckInCommonType.余额:
                                    money += p.num;
                                    //储值余额
                                    await _userBalanceServices.Change(entity.userId, (int)GlobalEnumVars.UserBalanceSourceTypes.CheckIn, p.num, id.ToString());
                                    break;
                            }
                        }
                        //原则上应该还要加个日志。确定是否这个时间已经领取过了。
                    }
                    cumulativeCheckInRules.ForEach(Action);


                    //判断连续签到次数是否满足
                    var continuousCheckInRules = await _continuousCheckInRulesServices.GetDataWidthChild();
                    //获取用户数据
                    var user = await _userServices.QueryByIdAsync(entity.userId);
                    //获取用户当前已经连续签到的次数
                    var userContinuousCheckInNum = userCheckIn.continuousCheckInCount;

                    //遍历处理结果
                    foreach (var rule in from p in continuousCheckInRules where p.days == userContinuousCheckInNum select p.details.Find(o => o.userGradeId == user.grade) into rule where rule != null select rule)
                    {
                        switch (rule.type)
                        {
                            case (int)GlobalEnumVars.CheckInCommonType.积分:
                                point += rule.num;
                                //储值积分
                                await _userPointLogServices.SetPoint(entity.userId, rule.num, (int)GlobalEnumVars.UserPointSourceTypes.PointTypeSign, "日历签到，获得" + rule.num + "积分");
                                break;
                            case (int)GlobalEnumVars.CheckInCommonType.余额:
                                money += rule.num;
                                //储值余额
                                await _userBalanceServices.Change(entity.userId, (int)GlobalEnumVars.UserBalanceSourceTypes.CheckIn, rule.num, id.ToString());
                                break;
                        }
                    }

                    jm.code = 0;
                    jm.msg = "签到成功共获得" + point + "积分" + money + "余额";
                    jm.data = userCheckIn;
                    jm.otherData = cumulativeCheckInRules;
                }
                else
                {
                    jm.code = 1;
                    jm.msg = "日历签到暂未开启";
                }
            }
            catch (Exception e)
            {
                jm.code = 1;
                jm.msg = "更新失败";
                jm.data = e;
            }
            return jm;
        }

    }
}
